/**
 * 定义 wx 全局变量.有可能不存在.使用前要进行判断.
 */
import CommonUtil from "../utils/CommonUtil";
import Toast from "../../app/popups/Toast";
import {settings} from "../../app/consts/Settings";

// @ts-ignore
export const wx: any = window.wx || false;

export default class Wx {
    public static isWeChatEnv(): boolean {
        return !!wx;
    }

    /**
     * 使用URL 创建一张图片Frame.
     * @param {string} avatarUrl
     * @returns {Promise<cc.SpriteFrame>}
     */
    public static createImage(avatarUrl: string): Promise<cc.SpriteFrame> {
        return new Promise<cc.SpriteFrame>(((resolve, reject) => {
            if (this.isWeChatEnv()) {
                const image = wx.createImage();
                image.onload = () => {
                    try {
                        const texture = new cc.Texture2D();
                        texture.initWithElement(image);
                        texture.handleLoadedTexture();
                        resolve(new cc.SpriteFrame(texture));
                    } catch (e) {
                        console.error(e);
                        reject(e);
                    }
                };
                image.src = avatarUrl;
            } else {
                let type = "jpg";
                if (avatarUrl.indexOf(".png") > 0) {
                    type = "png";
                }
                cc.loader.load(
                    {
                        url: avatarUrl, type,
                    },
                    (err, texture) => {
                        if (!err) {
                            resolve(new cc.SpriteFrame(texture));
                        } else {
                            console.error("加载图片失败:", avatarUrl);
                            resolve(new cc.SpriteFrame());
                        }
                    });
            }
        }));
    }

    /**
     * 显示微信提示弹窗
     */
    public static toast(msg: string) {
        if (this.isWeChatEnv()) {
            wx.showToast({title: msg, duration: 3000});
        }
    }

    public static navigateToMiniProgram(addid: string, path: string): Promise<any> {
        return new Promise<boolean>((resolve) => {
            if (this.isWeChatEnv()) {
                wx.navigateToMiniProgram({
                    appId: addid,
                    path: path,
                    success() {
                        resolve(true);
                    },
                    fail() {
                        resolve(false);
                        Toast.showToast("跳转失败,请稍后重试!");
                    }
                })
            } else {
                resolve(false);
            }
        });
    }

    /**
     * 显示微信模态框
     * return 用户是否点击确定按钮.
     */
    public static dialog(title: string, content: string, confirmText?: string, confirmColor?: string,
                         showCancel?: boolean, cancelText?: string, cancelColor?: string): Promise<boolean> {
        return new Promise<boolean>((resolve) => {
            if (this.isWeChatEnv()) {
                wx.showModal({
                    title,
                    content,
                    showCancel: showCancel || false,
                    cancelText: cancelText || "取消",
                    confirmText: confirmText || "确定",
                    confirmColor: confirmColor || "#3cc51f",
                    cancelColor: cancelColor || "#000000",
                    success: (ret) => {
                        resolve(ret.confirm || false);
                    },
                    fail: () => {
                        resolve(false);
                    },
                });
            } else {
                resolve(false);
            }
        });
    }

    /**
     * 显示一个loading 框.用于提示等待.
     * @param {string} title
     * @param {boolean} mask
     */
    public static loading(title: string, mask: boolean = false) {
        if (this.isWeChatEnv()) {
            wx.showLoading({
                title: title || "",
                mask,
            });
        }
    }

    /**
     * 隐藏进度框.
     */
    public static hideLoading() {
        if (this.isWeChatEnv()) {
            wx.hideLoading();
        }
    }

    /**
     * 预览图片.在微信中可对图片进行长按等操作.
     * @param {string[]} urls
     * @returns {Promise<boolean>}
     */
    public static previewImage(...urls: string[]): Promise<boolean> {
        return new Promise<boolean>((resolve) => {
            if (this.isWeChatEnv()) {
                wx.previewImage({
                    urls,
                    success: () => {
                        resolve(true);
                    },
                    fail: () => {
                        resolve(false);
                    },
                });
            } else {
                resolve(false);
            }
        });
    }

    /**
     * 获取系统信息.
     * @returns {Promise<>}
     */
    public static getSystemInfo(): Promise<any> {
        return new Promise<any>((resolve) => {
            resolve(wx.getSystemInfoSync());
        });
    }

    public static getSdkVersion(): string {
        if (!this.isWeChatEnv()) {
            return "";
        }
        const sysInfo = wx.getSystemInfoSync();
        return sysInfo.SDKVersion;
    }

    public static getSystemInfoSync(): any {
        if (!this.isWeChatEnv()) {
            return false;
        }
        return wx.getSystemInfoSync();
    }

    // 真实尺寸转化为微信尺寸信息.
    public static realSize2Wx(inout: { x: number, y: number, width: number, height: number })
        : { x: number, y: number, width: number, height: number } {
        let sysInfo = this.getSystemInfoSync();
        if (!sysInfo) {
            return inout;
        }
        let ratioX = sysInfo.windowWidth / cc.winSize.width;
        let ratioY = sysInfo.windowHeight / cc.winSize.height;
        inout.x = Math.round(inout.x * ratioX);
        inout.y = Math.round(inout.y * ratioY);
        inout.width = Math.round(inout.width * ratioX);
        inout.height = Math.round(inout.height * ratioY);
        return inout;
    }


    // 判断是否是iphonex 手机.
    public static isIPX(): boolean {
        if (this.isWeChatEnv()) {
            const sysInfo = Wx.getSystemInfoSync();
            return (sysInfo && sysInfo.model.toUpperCase().indexOf("IPHONE X") >= 0)
        } else {
            return false;
        }
    }

    /**
     * 使用WX 下载文件.并保存文件,返回保存的文件路径.
     * @param _url
     * @param header
     * @returns {Promise<string>}
     */
    public static download(_url: string, header?: any): Promise<string> {
        let url = _url;
        url += `?_ts=${Date.now()}`;
        return new Promise<string>((resolve, reject) => {
            if (this.isWeChatEnv()) {
                wx.downloadFile({
                    url, header: header || {}, success: (ret) => {
                        wx.getFileSystemManager().saveFile({
                            tempFilePath: ret.tempFilePath, success: (res) => {
                                resolve(res.savedFilePath);
                            },
                        });
                    },
                    fail: () => {
                        reject();
                    },
                });
            } else {
                return Promise.resolve(null)
            }
        });
    }

    public static getUserInfo(withCredentials: boolean = false): Promise<any> {
        if (!cc.sys.isObjectValid(wx)) {
            return Promise.resolve({});
        } else {
            return new Promise<any>((resolve) => {
                wx.getUserInfo({
                    withCredentials,
                    success(user: any) {
                        cc.log("请求授权成功.");
                        resolve(user);
                    },
                    fail(er) {
                        cc.log("请求授权失败.", er);
                        resolve({userInfo: {nickName: "anymous", avatarUrl: ""}});
                    },
                    complete() {
                    },
                });
            });
        }
    }

    // 适配微信游戏平台.
    public static post(url, header?: any, body?: any, method?: string): Promise<any> {
        // 判断wx对象是否存在.
        // if (this.isWeChatEnv()) {
        //     return new Promise<any>((resolve, reject) => {
        //         wx.request({
        //             url,
        //             header: Common.assign(header, {}),
        //             data: body || {},
        //             method: method || "POST",
        //             success(res) {
        //                 if (res.statusCode !== 200) {
        //                     console.warn("网络请求失败:", res)
        //                 }
        //                 if (CC_DEBUG) {
        //                     cc.log(url, res)
        //                 }
        //                 resolve(res.data);
        //             },
        //             fail(reason) {
        //                 cc.log("网络请求失败, 重试一次.");
        //                 wx.request({
        //                     url,
        //                     header: Common.assign(header, {}),
        //                     data: body || {},
        //                     method: method || "POST",
        //                     success(res) {
        //                         resolve(res.data);
        //                     },
        //                     fail(reason) {
        //                         // 统计网络异常.
        //                         logger.sendEvent("请求失败", {url: url, reason});
        //                         reject(reason);
        //                     },
        //                 });
        //             },
        //         });
        //     });
        // } else {
        return CommonUtil.post(url, header, body, method || "POST");
        // }
    }

    // 登录微信平台
    public static loginWeChat(): Promise<any> {
        return new Promise<any>((resolve, reject) => {
            if (cc.sys.isObjectValid(wx)) {
                wx.login({
                    success(res: any) {
                        cc.log("微信登录成功.", res);
                        resolve(res);
                    },
                    failed(ret) {
                        cc.log("微信登录失败.", ret);
                        reject(ret);
                    },
                    complete(res) {
                        cc.log("微信登录完成.", res);
                    },
                });
            } else {
                resolve({});
            }
        });
    }

    public static authorize(scope: string): Promise<boolean> {
        return new Promise<any>((resolve,) => {
            wx.authorize({
                scope: scope,
                fail(res) {
                    // iOS 和 Android 对于拒绝授权的回调 errMsg 没有统一，需要做一下兼容处理
                    if (res.errMsg.indexOf('auth deny') > -1 || res.errMsg.indexOf('auth denied') > -1) {
                        // 处理用户拒绝授权的情况
                        Toast.showToast("用户未登录时无法使用全国排行榜功能.");
                        resolve(false)
                    }
                },
                success() {
                    resolve(true);
                }
            })
        })
    }

    public static isScopeAuthed(scope: string): Promise<boolean> {
        if (!Wx.isWeChatEnv()) {
            return Promise.resolve(true);
        }
        return new Promise<boolean>(resolve => {
            wx.getSetting({
                success(ret) {
                    cc.log("用户授权情况:", ret);
                    resolve(ret.authSetting[scope]);
                },
                fail(ret) {
                    cc.log("检查授权失败", ret);
                    resolve(false);
                }
            })
        })
    }

    public static openSetting(scope?: string): Promise<any> {
        return new Promise<any>(resolve => {
            wx.openSetting({
                success(ret) {
                    cc.log("用户授权情况:", ret);
                    resolve(ret.authSetting[scope]);
                },
                fail(ret) {
                    cc.log("检查授权失败", ret);
                    resolve(false);
                }
            });
        })
    }

    /**
     * 退出游戏.
     */
    public static exit() {
        if (Wx.isWeChatEnv()) {
            wx.exitMiniProgram({
                complete() {
                    cc.log("退出游戏成功");
                }
            });
        }
    }

    // 微信振动.
    public static vibrate(long: boolean = false) {
        if (Wx.isWeChatEnv()) {
            const vib = settings.effectOpen;
            if (!vib) {
                return;
            }
            if (cc.sys.now() - this.lastVibrate < 100) {
                return;
            }
            this.lastVibrate = cc.sys.now();

            if (long) {
                wx.vibrateLong();
            } else {
                wx.vibrateShort();
            }
        }
    }

    // 上传微信子域排行数据,可直接在主域中使用.
    public static updateUserData(key: string, data: any, sortKey?: string): Promise<any> {
        if (!Wx.isWeChatEnv()) {
            return Promise.resolve();
        }
        if (!key || !data) {
            return;
        }
        return new Promise<any>((resolve, reject) => {
            // 为data自动增加一个uuid, 用来进行自身数据的查找. 否则不知道排行中哪一条是自己.
            data.uuid = "" + Math.random();

            // 增加时间戳,用来进行排行数据过滤.
            data.timestamp = cc.sys.now();

            // 增加小游戏中心排行显示.
            if (sortKey) {
                data.wxgame = {score: data[sortKey], update_time: data.timestamp}
            }
            wx.setUserCloudStorage({
                KVDataList: [{
                    key: key,
                    value: JSON.stringify(data)
                }],
                success: function (args) {
                    cc.log("上传排行榜成功.", args);
                    resolve(args);
                },
                fail: function (args) {
                    cc.log("上传排行榜失败.", args);
                    reject(args);
                }
            })
        })
    }

    // 删除微信子域数据.
    public static removeUserData(...keys: string[]) {
        if (!Wx.isWeChatEnv()) {
            return
        }
        wx.removeUserCloudStorage({
            keyList: keys,
            success() {
                cc.log("清除玩家数据成功.");
            },
            fail() {
                cc.log("清除玩家数据失败.", keys);
            }
        })
    }

    public static getShareContext(): any {
        if (!Wx.isWeChatEnv()) {
            return null
        }
        return wx.getOpenDataContext();
    }

    // 获取子域context.
    public static getShareCanvas(): any {
        if (!Wx.isWeChatEnv()) {
            return null
        }
        const context = wx.getOpenDataContext();
        return context.canvas
    }

    // 清空子域绘制.
    public static clearSubContext() {
        if (!Wx.isWeChatEnv()) {
            return;
        }
        const context = wx.getOpenDataContext();
        if (context) {
            context.width = cc.winSize.width;
            context.height = cc.winSize.height;
            cc.log("屏幕尺寸:", cc.winSize);
        }
    }

    // 向子域同步指令.
    public static sendMsgToContext(what: number | string, args: any) {
        const context = this.getShareContext();
        if (context == null) {
            console.info("微信环境异常.无法调用context.");
            return
        }
        context.postMessage({what, arguments: args});
    }

    public static clearUserCloudStorage(keys: string[]) {
        if (Wx.isWeChatEnv()) {
            wx.removeUserCloudStorage({
                keyList: keys || [],
                success(res) {
                    console.warn("已成功清除微信托管数据", res)
                }
            })
        }
    }

    // 检测是否是从我的小程序进入的.
    public static async checkEnterFromMiniProgram() {
        if (Wx.isWeChatEnv()) {
            const launchOptions = wx.getLaunchOptionsSync();
            cc.log("启动参数:=====", launchOptions, !!(launchOptions.query && launchOptions.query.scene == 1104));
            return !!(launchOptions && launchOptions.scene == 1104);
        }
        return false;
    }

    public static gc() {
        if (Wx.isWeChatEnv()) {
            wx.triggerGC();
        }
    }

    public static onMemoryWarning(callback: Function) {
        if (Wx.isWeChatEnv()) {
            wx.onMemoryWarning(callback);
        }
    }

    private static lastVibrate: number = 0;

}
